local assets =
{
    Asset("ANIM", "anim/sw_pig_cannon.zip"),
}

local weapon_prefabs =
{
    "sw_piggy_bomb",
    "sw_piggy_bomb_proj",
}

----------------------------------------------------------------------------------------------------------------------------

local function OnEquip(inst, owner)
    local skin_build = inst:GetSkinBuild()
    if skin_build ~= nil then
        owner:PushEvent("equipskinneditem", inst:GetSkinName())
        owner.AnimState:OverrideItemSkinSymbol("swap_object", skin_build, "swap_sw_pig_cannon", inst.GUID, "swap_sw_pig_cannon")
    else
        owner.AnimState:OverrideSymbol("swap_object", "sw_pig_cannon", "swap_sw_pig_cannon")
    end

    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")

    if inst.components.container ~= nil then
        inst.components.container:Open(owner)
    end
end

local function OnUnequip(inst, owner)
    local skin_build = inst:GetSkinBuild()
    if skin_build ~= nil then
        owner:PushEvent("unequipskinneditem", inst:GetSkinName())
    end

    owner.AnimState:Hide("ARM_carry")
    owner.AnimState:Show("ARM_normal")

    if inst.components.container ~= nil then
        inst.components.container:Close()
    end
end

local function OnEquipToModel(inst, owner)
    if inst.components.container ~= nil then
        inst.components.container:Close()
    end
end

----------------------------------------------------------------------------------------------------------------------------

-- 发射时移除格子中物品
local function OnProjectileLaunched(inst, attacker, target)
    if inst.components.container ~= nil then
        local ammo_stack = inst.components.container:GetItemInSlot(1)
        local item = inst.components.container:RemoveItem(ammo_stack, false)

        if item ~= nil then
            item:Remove()
        end
    end
end

local function switch_short_mode(inst)
    local item = inst.components.container:GetItemInSlot(1)
    if inst.components.weapon ~= nil and item ~= nil and item.prefab == "sw_piggy_bomb" then
        inst.components.weapon:SetProjectile("sw_piggy_bomb_proj1")
        inst.components.weapon:SetRange(2)
    elseif inst.components.weapon ~= nil and item ~= nil and item.prefab == "sw_enlight_piggy_bomb" then
        inst.components.weapon:SetProjectile("sw_enlight_piggy_bomb_proj1")
        inst.components.weapon:SetRange(2)
    elseif inst.components.weapon ~= nil and item ~= nil and item.prefab == "sw_shadow_piggy_bomb" then
        inst.components.weapon:SetProjectile("sw_shadow_piggy_bomb_proj1")
        inst.components.weapon:SetRange(2)
    end
end

local function switch_long_mode(inst)
    local item = inst.components.container:GetItemInSlot(1)
    if inst.components.weapon ~= nil and item ~= nil and item.prefab == "sw_piggy_bomb" then
        inst.components.weapon:SetProjectile("sw_piggy_bomb_proj")
        inst.components.weapon:SetRange(18)
    elseif inst.components.weapon ~= nil and item ~= nil and item.prefab == "sw_enlight_piggy_bomb" then
        inst.components.weapon:SetProjectile("sw_enlight_piggy_bomb_proj")
        inst.components.weapon:SetRange(18)
    elseif inst.components.weapon ~= nil and item ~= nil and item.prefab == "sw_shadow_piggy_bomb" then
        inst.components.weapon:SetProjectile("sw_shadow_piggy_bomb_proj")
        inst.components.weapon:SetRange(18)
    end
end

local function OnAmmoLoaded(inst, data)
    if inst.components.weapon ~= nil and data ~= nil and data.item ~= nil then
        if inst.mode == "long" then
            switch_long_mode(inst)
        elseif inst.mode == "short" then
            switch_short_mode(inst)
        end
        inst:AddTag("blowpipe") -- 改变玩家攻击动作
        inst:AddTag("rangedweapon")
    end
end

-- 参考上方函数注释
local function OnAmmoUnloaded(inst, data)
    if inst.components.weapon ~= nil then
        inst.components.weapon:SetProjectile(nil)
        inst.components.weapon:SetRange(nil)
        inst:RemoveTag("blowpipe")
        inst:RemoveTag("rangedweapon")
    end
end

local function switch_mode(inst)
    local owner = inst.components.inventoryitem.owner
    if inst.mode == "long" then
        inst.mode = "short"
        switch_short_mode(inst)
        if owner and owner.components.talker then
            owner.components.talker:Say(STRINGS.SW_STRINGS.MODE1, 2)
        end
    else
        inst.mode = "long"
        switch_long_mode(inst)
        if owner and owner.components.talker then
            owner.components.talker:Say(STRINGS.SW_STRINGS.MODE2, 2)
        end
    end
    return false
end

local function OnUpgrade(inst, performer, upgraded_from_item)
    local numupgrades = inst.components.upgradeable.numupgrades
    if numupgrades == 1 then
        inst._chestupgrade_stacksize = true
        if inst.components.container ~= nil then -- 注释(JBK): 容器组件在烧毁的过程中消失，但我们仍然希望应用构建。
            inst.components.container:Close()
            inst.components.container:EnableInfiniteStackSize(true)
        end
        if upgraded_from_item then
            local x, y, z = inst.Transform:GetWorldPosition()
            local fx = SpawnPrefab("chestupgrade_stacksize_fx")
            fx.Transform:SetPosition(x, y, z)
        end
    end
    inst.components.upgradeable.upgradetype = nil
end

local function regular_OnDecontructStructure(inst, caster)
    if inst.components.upgradeable ~= nil and inst.components.upgradeable.numupgrades > 0 then
        if inst.components.lootdropper ~= nil then
            inst.components.lootdropper:SpawnLootPrefab("alterguardianhatshard") -- 拆解额外获得一个启迪碎片
        end
    end
    inst.components.container:DropEverything()
end

----------------------------------------------------------------------------------------------------------------------------

local function onsave(inst, data)
    data.mode = inst.mode
end

local function onpreload(inst, data)
    if data then
        if data.mode then
            inst.mode = data.mode
        end
    end
end

local function OnLoad(inst)
    if inst.mode and inst.mode == "short" then
        switch_short_mode(inst)
    else
        switch_long_mode(inst)
    end

    if inst.components.upgradeable ~= nil and inst.components.upgradeable.numupgrades > 0 then
        OnUpgrade(inst)
    end
end

local function WeaponFn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)

    inst.AnimState:SetBank("sw_pig_cannon")
    inst.AnimState:SetBuild("sw_pig_cannon")
    inst.AnimState:PlayAnimation("idle")

    inst:AddTag("weapon")

    MakeInventoryFloatable(inst)

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst.mode           = "long"

    inst.OnAmmoLoaded   = OnAmmoLoaded   -- 弹药装填时.
    inst.OnAmmoUnloaded = OnAmmoUnloaded -- 弹药卸载时.

    inst:AddComponent("inspectable")
    inst:AddComponent("inventoryitem")

    inst:AddComponent("equippable")
    inst.components.equippable:SetOnEquip(OnEquip)
    inst.components.equippable:SetOnUnequip(OnUnequip)
    inst.components.equippable:SetOnEquipToModel(OnEquipToModel)

    inst:AddComponent("weapon")
    inst.components.weapon:SetDamage(TUNING.UNARMED_DAMAGE)
    -- 发射时设置
    inst.components.weapon:SetOnProjectileLaunched(OnProjectileLaunched)

    inst:AddComponent("container")
    inst.components.container:WidgetSetup("sw_pig_cannon")

    inst:ListenForEvent("itemget", inst.OnAmmoLoaded)
    inst:ListenForEvent("itemlose", inst.OnAmmoUnloaded)

    inst:AddComponent("useableitem")
    inst.components.useableitem:SetOnUseFn(switch_mode)

    local upgradeable = inst:AddComponent("upgradeable")
    upgradeable.upgradetype = UPGRADETYPES.CHEST
    upgradeable:SetOnUpgradeFn(OnUpgrade)

    inst.OnSave = onsave
    inst.OnPreLoad = onpreload
    inst.OnLoad = OnLoad

    inst:ListenForEvent("ondeconstructstructure", regular_OnDecontructStructure)

    MakeHauntableLaunch(inst)

    return inst
end

return Prefab("sw_pig_cannon", WeaponFn, assets, weapon_prefabs)
